from OWRpy import *
import os.path, redREnviron
import redRi18n
_ = redRi18n.get_(package = 'base')
import signals
import redRGUI

class standardize(OWRpy): 
    globalSettingsList = ['commit']
    def __init__(self, **kwargs):
        OWRpy.__init__(self, **kwargs)

        # Python variables
        self.data = {}
        self.RFunctionParam_object = ''
        
        #create R variables in the R session. 
        self.setRvariableNames(["standardize"])
        
        #Inputs
        self.inputs.addInput('id0', _('R Variable Object'), signals.base.RDataFrame, self.processobject)
        
        #Outputs
        self.outputs.addOutput('id0', 'Standardized', signals.base.RMatrix) # should output dissimilaroty signal
		
        #GUI
        self.RFunctionParam_method = redRGUI.base.comboBox(self.controlArea,  label = "Method: ",
        items = [('total', 'Total'),('max', 'Max'),('freq', 'Freq'),('normalize', 'Normalize'),('standardize', 'Standardize'),
        ('pa', 'Presence/Absence'),('chi.square', 'Chi square'),('hellinger', 'Hellinger'),('log', 'Log')],editable=False, callback = self.onMethodChange)#,('range','Range')
        
        self.RFunctionParam_description = redRGUI.base.textEdit(self.controlArea, label = "Method description: ", html = 'Total: Divide by margin total', editable=False, height=100)
                
        self.RFunctionParam_margin = redRGUI.base.radioButtons(self.controlArea,  label = "Size signifiance", 
        buttons = [('1','by row'),('2','by columns')], setChecked='1',orientation='horizontal')
        
        self.RFunctionParam_options = redRGUI.base.checkBox(self.controlArea,  label = "Options", 
        buttons = [('na.rm','Ignore missing values in row or column standardizations.')],
        setChecked=None,orientation='vertical')
        
        # if log
        self.RFunctionParam_methodLog = redRGUI.base.groupBox(self.controlArea, label='Log options')
        self.RFunctionParam_logbase = redRGUI.base.lineEdit(self.RFunctionParam_methodLog, label = "logarithm base", text = '2')
        self.RFunctionParam_methodLog.hide()
        
        #Commit
        self.commit = redRGUI.base.commitButton(self.bottomAreaRight, _("Commit"), alignment=Qt.AlignLeft, 
        callback = self.commitFunction, processOnInput=True)

    def onMethodChange(self):
        print self.RFunctionParam_method.currentId()
        if self.RFunctionParam_method.currentId() =='total':
            self.RFunctionParam_description.setText('Total: divide by margin total')
            self.RFunctionParam_margin.setChecked('1')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='max':
            self.RFunctionParam_description.setText('Max: divide by margin maximum')
            self.RFunctionParam_margin.setChecked('2')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='freq':
            self.RFunctionParam_description.setText('Freq: divide by margin maximum and multiply by the number of non-zero items, so that the average of non-zero entries is one (Oksanen 1983)')
            self.RFunctionParam_margin.setChecked('2')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='normalize':
            self.RFunctionParam_description.setText('Normalize: make margin sum of squares equal to one')
            self.RFunctionParam_margin.setChecked('2')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='range':
            self.RFunctionParam_description.setText('Range: standardize values into range 0 ... 1. If all values are constant, they will be transformed to 0.')
            self.RFunctionParam_margin.setChecked('2')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='standardize':
            self.RFunctionParam_description.setText('Standardize: scale x to zero mean and unit variance')
            self.RFunctionParam_margin.setChecked('2')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='pa':
            self.RFunctionParam_description.setText('PA: scale x to presence/absence scale (0/1).')
            self.RFunctionParam_margin.setChecked('1')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='chi.square':
            self.RFunctionParam_description.setText('Chi.square: divide by row sums and square root of column sums, and adjust for square root of matrix total (Legendre & Gallagher 2001). When used with the Euclidean distance, the distances should be similar to the Chi-square distance used in correspondence analysis. However, the results from cmdscale would still differ, since CA is a weighted ordination method.')
            self.RFunctionParam_margin.setChecked('1')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='hellinger':
            self.RFunctionParam_description.setText('Hellinger: square root of method = "total" (Legendre & Gallagher 2001).')
            self.RFunctionParam_margin.setChecked('1')
            self.RFunctionParam_methodLog.hide()
        elif self.RFunctionParam_method.currentId() =='log':
            self.RFunctionParam_methodLog.show()
            self.RFunctionParam_description.setText('Log: logarithmic transformation as suggested by Anderson et al. (2006): log_b (x) + 1 for x > 0, where b is the base of the logarithm; zeros are left as zeros. Higher bases give less weight to quantities and more to presences, and logbase = Inf gives the presence/absence scaling. Please note this is not log(x+1). Anderson et al. (2006) suggested this for their (strongly) modified Gower distance, but the standardization can be used independently of distance indices.')
            self.RFunctionParam_margin.setChecked('by row')
            
        
    def processobject(self, data):
        if not self.require_librarys(["vegan"]):
            self.status.setText('R Libraries Not Loaded.')
            return
        if data:
            self.RFunctionParam_object=data.getData()
            self.data = data
            if self.commit.processOnInput():
                self.commitFunction()
        else:
            self.RFunctionParam_object=''
    def commitFunction(self):
        
        if unicode(self.RFunctionParam_object) == '':
            self.status.setText('No data.')
            return

        if self.RFunctionParam_method.currentId() == '':
            self.status.setText('No method selected.')
            return
    
        injection = []
        if self.RFunctionParam_margin.getCheckedId() == '1': 
            string='MARGIN=1'
            injection.append(string)
        elif self.RFunctionParam_margin.getCheckedId() == '2': 
            string='MARGIN=2'
            injection.append(string)
        if self.RFunctionParam_method.currentId() == 'log' :
            string='logbase='+unicode(self.RFunctionParam_logbase.text())+''
            injection.append(string)
        if 'na.rm' in self.RFunctionParam_options.getCheckedIds(): 
            string='na.rm=TRUE'
            injection.append(string)
        else:
            string='na.rm=FALSE'
            injection.append(string)

        inj = ','.join(injection)
                
        print 'inj: ', inj

        self.R(self.Rvariables['standardize']+'<-decostand(x='+unicode(self.RFunctionParam_object)+
        ', method="'+unicode(self.RFunctionParam_method.currentId())+'", '+inj+')', processingNotice=True)      
        
        
        #self.R(self.Rvariables['dissimilarity']+'<-vegdist(x='+unicode(self.RFunctionParam_object)+', method="'+unicode(self.redRdissimilarityMethod.currentId())+'")')  
        
        self.newData = signals.base.RMatrix(self, data = self.Rvariables["standardize"], checkVal=False)
        self.rSend("id0", self.newData)
        
